﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.FactionManager
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System.Collections.Generic;
using System.Linq;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem
{
  public class FactionManager
  {
    [SaveableField(20)]
    private FactionManagerStancesData _stances;

    internal static void AutoGeneratedStaticCollectObjectsFactionManager(
      object o,
      List<object> collectedObjects)
    {
      ((FactionManager) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      collectedObjects.Add((object) this._stances);
    }

    internal static object AutoGeneratedGetMemberValue_stances(object o)
    {
      return (object) ((FactionManager) o)._stances;
    }

    public static FactionManager Instance => Campaign.Current.FactionManager;

    public FactionManager() => this._stances = new FactionManagerStancesData();

    internal void AfterLoad()
    {
      foreach (StanceLink stanceLink in this._stances.GetStanceLinks().ToList<StanceLink>())
      {
        if (stanceLink.Faction1 != stanceLink.Faction2)
        {
          if (!stanceLink.Faction1.IsEliminated && !stanceLink.Faction2.IsEliminated)
          {
            FactionManager.AddStanceToFaction(stanceLink.Faction1, stanceLink);
            FactionManager.AddStanceToFaction(stanceLink.Faction2, stanceLink);
          }
          else
            this.RemoveStance(stanceLink);
        }
      }
    }

    internal StanceLink GetStanceLinkInternal(IFaction faction1, IFaction faction2)
    {
      StanceLink stanceLink = this._stances.GetStance(faction1, faction2);
      if (stanceLink == null)
      {
        bool isAtConstantWar = faction1.IsBanditFaction && !faction2.IsBanditFaction || !faction1.IsBanditFaction && faction2.IsBanditFaction;
        stanceLink = new StanceLink(isAtConstantWar ? StanceType.War : StanceType.Neutral, faction1, faction2, isAtConstantWar);
        this.AddStance(faction1, faction2, stanceLink);
      }
      return stanceLink;
    }

    private void AddStance(IFaction faction1, IFaction faction2, StanceLink stanceLink)
    {
      if (faction1.IsEliminated || faction2.IsEliminated)
        return;
      this._stances.AddStance(stanceLink);
      FactionManager.AddStanceToFaction(faction1, stanceLink);
      FactionManager.AddStanceToFaction(faction2, stanceLink);
    }

    private void RemoveStance(StanceLink stance)
    {
      this._stances.RemoveStance(stance);
      FactionManager.RemoveStanceFromFaction(stance.Faction1, stance);
      FactionManager.RemoveStanceFromFaction(stance.Faction2, stance);
    }

    private static void AddStanceToFaction(IFaction faction1, StanceLink stanceLink)
    {
      if (faction1 is Kingdom kingdom)
        kingdom.AddStanceInternal(stanceLink);
      else
        (faction1 as Clan).AddStanceInternal(stanceLink);
    }

    private static void RemoveStanceFromFaction(IFaction faction1, StanceLink stanceLink)
    {
      if (faction1 is Kingdom kingdom)
        kingdom.RemoveStanceInternal(stanceLink);
      else
        (faction1 as Clan).RemoveStanceInternal(stanceLink);
    }

    private static StanceLink SetStance(
      IFaction faction1,
      IFaction faction2,
      StanceType stanceType)
    {
      StanceLink stanceLinkInternal = FactionManager.Instance.GetStanceLinkInternal(faction1, faction2);
      stanceLinkInternal.StanceType = stanceType;
      return stanceLinkInternal;
    }

    public static void DeclareAlliance(IFaction faction1, IFaction faction2)
    {
      if (faction1 == faction2 || faction1.IsBanditFaction || faction2.IsBanditFaction)
        return;
      FactionManager.SetStance(faction1, faction2, StanceType.Neutral);
    }

    public static void DeclareWar(IFaction faction1, IFaction faction2, bool isAtConstantWar = false)
    {
      if (faction1 == faction2 || faction1.IsBanditFaction || faction2.IsBanditFaction)
        return;
      FactionManager.SetStance(faction1, faction2, StanceType.War).IsAtConstantWar = isAtConstantWar;
    }

    public static void SetNeutral(IFaction faction1, IFaction faction2)
    {
      if (faction1 == faction2 || faction1.IsBanditFaction || faction2.IsBanditFaction)
        return;
      FactionManager.Instance.GetStanceLinkInternal(faction1, faction2).StanceType = StanceType.Neutral;
    }

    public static bool IsAtWarAgainstFaction(IFaction faction1, IFaction faction2)
    {
      return faction1 != null && faction2 != null && faction1 != faction2 && !faction1.IsEliminated && !faction2.IsEliminated && FactionManager.Instance.GetStanceLinkInternal(faction1, faction2).IsAtWar;
    }

    public static bool IsAlliedWithFaction(IFaction faction1, IFaction faction2)
    {
      if (faction1 == null || faction2 == null || faction1.IsEliminated || faction2.IsEliminated)
        return false;
      if (faction1 == faction2)
        return true;
      StanceLink stanceLinkInternal = FactionManager.Instance.GetStanceLinkInternal(faction1, faction2);
      return stanceLinkInternal != null && stanceLinkInternal.IsAllied;
    }

    public static bool IsNeutralWithFaction(IFaction faction1, IFaction faction2)
    {
      if (faction1 == null || faction2 == null || faction1 == faction2 || faction1.IsEliminated || faction2.IsEliminated)
        return false;
      StanceLink stanceLinkInternal = FactionManager.Instance.GetStanceLinkInternal(faction1, faction2);
      if (stanceLinkInternal == null && (faction1.IsBanditFaction && !faction2.IsBanditFaction && !faction2.IsOutlaw || faction2.IsBanditFaction && !faction1.IsBanditFaction && !faction1.IsOutlaw))
        return false;
      return stanceLinkInternal == null || stanceLinkInternal.IsNeutral;
    }

    internal void RemoveFactionsFromCampaignWars(IFaction faction1)
    {
      if (faction1.MapFaction != faction1)
        return;
      foreach (StanceLink stance in faction1.Stances.ToArray<StanceLink>())
        this.RemoveStance(stance);
    }

    public static IEnumerable<IFaction> GetEnemyFactions(IFaction faction)
    {
      foreach (StanceLink stance in faction.Stances)
      {
        if (stance.IsAtWar)
        {
          IFaction enemyFaction = (IFaction) null;
          if (stance.Faction1 == faction)
            enemyFaction = stance.Faction2;
          else if (stance.Faction2 == faction)
            enemyFaction = stance.Faction1;
          if (enemyFaction.IsMapFaction && !enemyFaction.IsBanditFaction)
            yield return enemyFaction;
        }
      }
    }

    public static IEnumerable<Kingdom> GetEnemyKingdoms(Kingdom faction)
    {
      foreach (StanceLink stance in faction.Stances)
      {
        if (stance.IsAtWar)
        {
          IFaction enemyKingdom = (IFaction) null;
          if (stance.Faction1 == faction)
            enemyKingdom = stance.Faction2;
          else if (stance.Faction2 == faction)
            enemyKingdom = stance.Faction1;
          if (enemyKingdom != null && enemyKingdom.IsKingdomFaction)
            yield return enemyKingdom as Kingdom;
        }
      }
    }

    public static int GetRelationBetweenClans(Clan clan1, Clan clan2)
    {
      float num1 = 0.0f;
      float num2 = 1E-05f;
      if (clan1.Lords.Count == 0 && clan1.IsBanditFaction && !clan2.IsBanditFaction || clan2.Lords.Count == 0 && clan2.IsBanditFaction && !clan1.IsBanditFaction)
        return -10;
      foreach (Hero lord1 in (List<Hero>) clan1.Lords)
      {
        if ((double) lord1.Age > (double) Campaign.Current.Models.AgeModel.HeroComesOfAge)
        {
          foreach (Hero lord2 in (List<Hero>) clan2.Lords)
          {
            if ((double) lord2.Age > (double) Campaign.Current.Models.AgeModel.HeroComesOfAge)
            {
              float num3 = 0.1f;
              if (lord1 == clan1.Leader)
                num3 += 0.2f;
              else if (lord1 == clan1.Leader?.Spouse)
                num3 += 0.05f;
              if (lord2 == clan2.Leader)
                num3 += 0.2f;
              else if (lord2 == clan2.Leader?.Spouse)
                num3 += 0.05f;
              if (lord1 == clan1.Leader && lord2 == clan2.Leader)
                num3 *= 20f;
              int baseHeroRelation = lord1.GetBaseHeroRelation(lord2);
              num1 += num3 * (float) baseHeroRelation;
              num2 += num3;
            }
          }
        }
      }
      return (int) ((double) num1 / (double) num2);
    }
  }
}
